package app.itgungnir.compose.wan.widgets

import android.content.res.Configuration
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Alarm
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.constraintlayout.compose.Dimension
import app.itgungnir.compose.wan.theme.WanComposePreviewTheme
import kotlinx.coroutines.launch
import kotlin.math.roundToInt

@Composable
fun WanDivider(
    modifier: Modifier = Modifier,
    fillWidth: Boolean = false,
    width: Dp = 1.dp,
    fillHeight: Boolean = false,
    height: Dp = 1.dp
) {
    Box(
        modifier = modifier
            .background(MaterialTheme.colors.onBackground.copy(alpha = 0.2F))
            .then(if (fillWidth) Modifier.fillMaxWidth() else Modifier.width(width))
            .then(if (fillHeight) Modifier.fillMaxHeight() else Modifier.height(height))
    )
}

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun WanBadge(
    modifier: Modifier = Modifier,
    badgeContent: @Composable (RowScope.() -> Unit)? = null,
    hideBadgeWhenBadgeContentIsNull: Boolean = false,
    content: @Composable BoxScope.() -> Unit
) {
    if (hideBadgeWhenBadgeContentIsNull && badgeContent == null) {
        Box(modifier = modifier) {
            content(this)
        }
    } else {
        BadgeBox(
            modifier = modifier,
            backgroundColor = MaterialTheme.colors.primary,
            contentColor = MaterialTheme.colors.onPrimary,
            badgeContent = badgeContent
        ) {
            content()
        }
    }
}

@Composable
fun WanDot(modifier: Modifier = Modifier, size: Dp = 10.dp) {
    Box(
        modifier = modifier
            .size(size)
            .clip(RoundedCornerShape(size = size / 2))
            .background(color = MaterialTheme.colors.primary)
    )
}

@Composable
fun WanCardRow(
    modifier: Modifier = Modifier,
    cornerRadius: Dp = 12.dp,
    onClick: (() -> Unit)? = null,
    horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
    verticalAlignment: Alignment.Vertical = Alignment.Top,
    content: @Composable RowScope.() -> Unit
) {
    Row(
        modifier = modifier
            .fillMaxWidth()
            .padding(start = 15.dp, end = 15.dp, top = 10.dp)
            .clip(RoundedCornerShape(cornerRadius))
            .background(MaterialTheme.colors.background)
            .then(if (onClick != null) Modifier.clickable { onClick.invoke() } else Modifier)
            .padding(horizontal = 15.dp, vertical = 10.dp),
        horizontalArrangement = horizontalArrangement,
        verticalAlignment = verticalAlignment
    ) {
        content(this)
    }
}

@Composable
fun WanCardColumn(
    modifier: Modifier = Modifier,
    cornerRadius: Dp = 12.dp,
    onClick: (() -> Unit)? = null,
    verticalArrangement: Arrangement.Vertical = Arrangement.Top,
    horizontalAlignment: Alignment.Horizontal = Alignment.Start,
    content: @Composable ColumnScope.() -> Unit
) {
    Column(
        modifier = modifier
            .fillMaxWidth()
            .padding(start = 15.dp, end = 15.dp, top = 10.dp)
            .clip(RoundedCornerShape(cornerRadius))
            .background(MaterialTheme.colors.background)
            .then(if (onClick != null) Modifier.clickable { onClick.invoke() } else Modifier)
            .padding(horizontal = 15.dp, vertical = 10.dp),
        verticalArrangement = verticalArrangement,
        horizontalAlignment = horizontalAlignment
    ) {
        content(this)
    }
}

data class WanSwipeMenuItem(
    val icon: ImageVector,
    val title: String,
    val backgroundColor: Color,
    val onClick: () -> Unit
)

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun WanSwipeMenuCard(
    modifier: Modifier = Modifier,
    cornerRadius: Dp = 12.dp,
    onClick: (() -> Unit)? = null,
    menuItems: List<WanSwipeMenuItem>,
    content: @Composable RowScope.() -> Unit
) {
    val coroutineScope = rememberCoroutineScope()
    val swipeableState = rememberSwipeableState(initialValue = 0)
    val menuItemWidth = 65.dp
    val menuItemWidthPx = with(LocalDensity.current) { menuItemWidth.toPx() }
    val menuCount = menuItems.size
    ConstraintLayout(
        modifier = modifier
            .fillMaxWidth()
            .then(
                if (menuCount > 0) {
                    Modifier.swipeable(
                        state = swipeableState,
                        anchors = mapOf(0F to 0, -menuCount * menuItemWidthPx to 1),
                        orientation = Orientation.Horizontal,
                        resistance = ResistanceConfig(0F, 0F, 0F)
                    )
                } else {
                    Modifier
                }
            )
    ) {
        val row = createRef()
        Row(
            modifier = Modifier
                .padding(end = 15.dp)
                .clip(RoundedCornerShape(topEnd = cornerRadius, bottomEnd = cornerRadius))
                .background(color = Color.Red)
                .constrainAs(row) {
                    end.linkTo(parent.end)
                    top.linkTo(parent.top)
                    bottom.linkTo(parent.bottom)
                    height = Dimension.fillToConstraints
                }
        ) {
            menuItems.take(3).forEachIndexed { index, item ->
                Column(
                    modifier = Modifier
                        .fillMaxHeight()
                        .width(if (index == 0) menuItemWidth + 12.dp else menuItemWidth)
                        .background(color = item.backgroundColor)
                        .clickable {
                            item.onClick.invoke()
                            coroutineScope.launch {
                                swipeableState.animateTo(targetValue = 0, anim = tween(durationMillis = 100))
                            }
                        }
                        .then(if (index == 0) Modifier.padding(start = 12.dp) else Modifier),
                    horizontalAlignment = Alignment.CenterHorizontally,
                    verticalArrangement = Arrangement.Center
                ) {
                    Icon(
                        modifier = Modifier.size(25.dp),
                        imageVector = item.icon,
                        contentDescription = "",
                        tint = MaterialTheme.colors.onPrimary
                    )
                    Spacer(modifier = Modifier.height(3.dp))
                    Text(
                        text = item.title,
                        color = MaterialTheme.colors.onPrimary,
                        style = MaterialTheme.typography.overline
                    )
                }
            }
        }
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(start = 15.dp, end = 15.dp)
                .then(
                    if (menuCount > 0) {
                        Modifier.offset { IntOffset(swipeableState.offset.value.roundToInt(), 0) }
                    } else {
                        Modifier
                    }
                )
                .clip(RoundedCornerShape(cornerRadius))
                .background(MaterialTheme.colors.background)
                .then(if (onClick != null) Modifier.clickable { onClick.invoke() } else Modifier)
                .padding(horizontal = 15.dp, vertical = 10.dp)
        ) {
            content(this)
        }
    }
}

@Preview(name = "WanBox light mode", showBackground = false)
@Preview(name = "WanBox dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = false)
@Composable
private fun WanBoxPreview() {
    WanComposePreviewTheme {
        Column(modifier = Modifier.padding(horizontal = 25.dp, vertical = 20.dp)) {
            WanBadge(badgeContent = { Text(text = "99+") }) {
                WanCardRow(verticalAlignment = Alignment.CenterVertically) {
                    WanDot(modifier = Modifier.padding(end = 10.dp), size = 20.dp)
                    WanHeader(content = "NonElevationCard Content")
                }
            }
            Spacer(modifier = Modifier.height(10.dp))
            WanDivider(fillWidth = true, height = 5.dp)
            Spacer(modifier = Modifier.height(10.dp))
            val menuItems = listOf(
                WanSwipeMenuItem(icon = Icons.Filled.Alarm, title = "标题", backgroundColor = Color.Red) {},
                WanSwipeMenuItem(icon = Icons.Filled.Alarm, title = "标题", backgroundColor = Color.Yellow) {}
            )
            WanSwipeMenuCard(menuItems = menuItems) {
                WanHeader(content = "SwipeMenuCard Content")
            }
            Spacer(modifier = Modifier.height(10.dp))
            WanDivider(fillWidth = true, height = 5.dp)
            WanCardColumn {
                WanHeader(content = "NonElevationCard Content")
            }
        }
    }
}
